//! # RustCloud 应用框架模块
//!
//! 该模块提供了 RustCloud 微服务应用的核心框架和生命周期管理功能。
//! 包括应用启动、服务注册、配置管理、优雅关闭等关键特性。
//!
//! ## 核心组件
//!
//! * **RustCloudApplication** - 应用核心类，管理应用生命周期
//! * **RustCloudApplicationBuilder** - 应用构建器，提供链式配置 API
//! * **RunConfig** - 运行时配置类，统一管理各组件配置
//!
//! ## 主要功能
//!
//! * **应用生命周期管理** - 启动、运行、关闭应用
//! * **服务注册发现** - 自动注册到注册中心和优雅注销
//! * **信号处理** - 支持 SIGINT、SIGTERM 等系统信号
//! * **错误处理** - 统一的错误处理和日志记录
//! * **跨平台支持** - 支持 Unix 和 Windows 系统
//!
//! ## 使用示例
//!
//! ```rust
//! use rustcloud_core::application::*;
//! use rustcloud_core::ApplicationConfig;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//!     // 使用构建器创建应用
//!     let app = RustCloudApplicationBuilder::new()
//!         .name("user-service")
//!         .version("1.0.0")
//!         .port(8080)
//!         .host("0.0.0.0")
//!         .metadata("env", "production")
//!         .build();
//!
//!     // 启动应用
//!     app.run().await?;
//!     
//!     Ok(())
//! }
//! ```

use crate::{
    ApplicationConfig, ServiceInstance, ServiceRegistry, ServiceResult, ServiceError
};
use std::sync::Arc;
use tokio::signal;
use tracing::{info, error, warn};

/// RustCloud 应用框架核心结构
///
/// 负责管理微服务应用的完整生命周期，包括应用启动、服务注册、配置管理和优雅关闭。
/// 提供了简洁的 API 来管理复杂的微服务基础设施，让开发者可以专注于业务逻辑。
///
/// # 组件特性
///
/// * **自动服务注册** - 启动时自动注册到注册中心
/// * **优雅关闭** - 支持信号处理和资源清理
/// * **配置驱动** - 基于配置的组件初始化
/// * **状态管理** - 线程安全的应用状态管理
/// * **错误处理** - 全面的错误处理和日志记录
///
/// # 生命周期阶段
///
/// 1. **初始化** - 加载配置，初始化组件
/// 2. **启动** - 注册服务，启动网络监听
/// 3. **运行** - 处理请求，监控健康状态
/// 4. **关闭** - 停止服务，注销注册，清理资源
///
/// # 使用示例
///
/// ```rust
/// use rustcloud_core::application::RustCloudApplication;
/// use rustcloud_core::ApplicationConfig;
///
/// async fn start_service() -> Result<(), Box<dyn std::error::Error>> {
///     // 创建应用配置
///     let config = ApplicationConfig {
///         name: "user-service".to_string(),
///         version: "1.0.0".to_string(),
///         port: 8080,
///         host: Some("0.0.0.0".to_string()),
///         ..Default::default()
///     };
///     
///     // 创建并启动应用
///     let app = RustCloudApplication::new(config);
///     app.run().await?;
///     
///     Ok(())
/// }
/// ```
///
/// # 注意事项
///
/// * 应用只能启动一次，重复启动会返回错误
/// * 关闭应用会消耗 self，无法重用
/// * 必须在异步环境中运行 (tokio runtime)
/// * 建议使用 RustCloudApplicationBuilder 来构建应用
#[derive(Clone)]
pub struct RustCloudApplication {
    /// 应用配置信息
    config: ApplicationConfig,
    /// 服务注册中心实例
    registry: Option<Arc<dyn ServiceRegistry>>,
    /// 当前服务实例信息
    service_instance: Option<ServiceInstance>,
    /// 应用是否已启动状态
    started: Arc<std::sync::atomic::AtomicBool>,
}

impl RustCloudApplication {
    /// 创建新的 RustCloud 应用实例
    /// 
    /// 使用指定的配置创建一个新的应用实例。创建后的应用处于未启动状态，
    /// 需要调用 `run()` 方法来启动应用。
    /// 
    /// # 参数
    /// 
    /// * `config` - 应用配置信息，包含服务名、版本、端口等
    /// 
    /// # 返回值
    /// 
    /// 返回一个新的 `RustCloudApplication` 实例
    /// 
    /// # 示例
    /// 
    /// ```rust
    /// use rustcloud_core::application::RustCloudApplication;
    /// use rustcloud_core::ApplicationConfig;
    /// 
    /// let config = ApplicationConfig::default();
    /// let app = RustCloudApplication::new(config);
    /// ```
    pub fn new(config: ApplicationConfig) -> Self {
        Self {
            config,
            registry: None,
            service_instance: None,
            started: Arc::new(std::sync::atomic::AtomicBool::new(false)),
        }
    }

    /// 设置服务注册中心
    /// 
    /// 为应用配置服务注册中心。设置后，应用在启动时会自动注册到指定的注册中心，
    /// 关闭时会自动注销。这是微服务发现的基础。
    /// 
    /// # 参数
    /// 
    /// * `registry` - 注册中心实例，需要实现 ServiceRegistry trait
    /// 
    /// # 返回值
    /// 
    /// 返回设置后的 `RustCloudApplication` 实例，支持链式调用
    /// 
    /// # 示例
    /// 
    /// ```rust
    /// # use std::sync::Arc;
    /// # use rustcloud_core::application::RustCloudApplication;
    /// # use rustcloud_core::{ApplicationConfig, ServiceRegistry};
    /// # 
    /// # struct MyRegistry;
    /// # impl ServiceRegistry for MyRegistry { /* 实现略 */ }
    /// # 
    /// let registry: Arc<dyn ServiceRegistry> = Arc::new(MyRegistry);
    /// let app = RustCloudApplication::new(ApplicationConfig::default())
    ///     .with_registry(registry);
    /// ```
    pub fn with_registry(mut self, registry: Arc<dyn ServiceRegistry>) -> Self {
        self.registry = Some(registry);
        self
    }

    /// 构建服务实例信息
    /// 
    /// 基于应用配置构建服务实例对象，包括服务标识、网络地址、元数据等信息。
    /// 该方法会自动添加版本、分组、命名空间等元数据信息。
    /// 
    /// # 返回值
    /// 
    /// 返回构建完成的 `ServiceInstance` 对象
    /// 
    /// # 元数据映射
    /// 
    /// * `version` - 应用版本号
    /// * `group` - 服务分组（如果配置了）
    /// * `namespace` - 命名空间（如果配置了）
    /// * 其他自定义元数据 - 从应用配置中复制
    fn build_service_instance(&self) -> ServiceInstance {
        let host = self.config.host.as_deref().unwrap_or("0.0.0.0");
        let mut instance = ServiceInstance::new(
            &self.config.name,
            host,
            self.config.port,
            "http",
        );

        // 添加应用元数据
        for (key, value) in &self.config.metadata {
            instance.add_metadata(key.clone(), value.clone());
        }

        // 添加版本信息
        instance.add_metadata("version", &self.config.version);
        
        // 添加分组信息
        if let Some(group) = &self.config.group {
            instance.add_metadata("group", group);
        }

        // 添加命名空间信息
        if let Some(namespace) = &self.config.namespace {
            instance.add_metadata("namespace", namespace);
        }

        instance
    }

    /// 启动应用并注册服务
    /// 
    /// 这是应用的主要启动方法，执行完整的启动流程包括服务验证、注册和信号监听。
    /// 该方法会阻塞当前线程直到收到关闭信号，因此通常在main函数的最后调用。
    /// 
    /// # 启动流程
    /// 
    /// 1. **状态检查** - 验证应用是否已经启动，避免重复启动
    /// 2. **实例构建** - 基于配置构建服务实例对象
    /// 3. **实例验证** - 验证服务实例的有效性（地址、端口等）
    /// 4. **服务注册** - 如果配置了注册中心，将服务注册到注册中心
    /// 5. **状态更新** - 标记应用为已启动状态
    /// 6. **信号监听** - 监听系统关闭信号，实现优雅关闭
    /// 
    /// # 返回值
    /// 
    /// * `Ok(())` - 应用成功启动和关闭
    /// * `Err(ServiceError)` - 启动过程中发生错误
    /// 
    /// # 错误类型
    /// 
    /// * `ConfigurationError` - 应用已启动或配置无效
    /// * `ValidationError` - 服务实例验证失败
    /// * `RegistryError` - 服务注册失败
    /// * `NetworkError` - 网络相关错误
    /// 
    /// # 使用示例
    /// 
    /// ```rust
    /// use rustcloud_core::application::RustCloudApplication;
    /// use rustcloud_core::ApplicationConfig;
    /// 
    /// #[tokio::main]
    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
    ///     let config = ApplicationConfig {
    ///         name: "my-service".to_string(),
    ///         version: "1.0.0".to_string(),
    ///         port: 8080,
    ///         ..Default::default()
    ///     };
    ///     
    ///     let app = RustCloudApplication::new(config);
    ///     app.run().await?;  // 这里会一直阻塞直到收到关闭信号
    ///     
    ///     Ok(())
    /// }
    /// ```
    /// 
    /// # 注意事项
    /// 
    /// * 该方法会消费self，因此只能调用一次
    /// * 方法会阻塞直到收到关闭信号（Ctrl+C、SIGTERM等）
    /// * 如果没有配置注册中心，服务仍然可以启动但不会被其他服务发现
    /// * 建议在生产环境中配置适当的日志级别以观察启动过程
    pub async fn run(mut self) -> ServiceResult<()> {
        // 检查是否已启动
        if self.started.load(std::sync::atomic::Ordering::Acquire) {
            return Err(ServiceError::ConfigurationError("Application already started".to_string()));
        }

        // 构建服务实例
        let service_instance = self.build_service_instance();
        
        // 验证服务实例
        service_instance.validate()?;

        // 如果配置了注册中心，则注册服务
        if let Some(registry) = &self.registry {
            info!("Registering service {} to registry at {}:{}", 
                  self.config.name, 
                  service_instance.host, 
                  service_instance.port);
            
            registry.register(service_instance.clone()).await
                .map_err(|e| {
                    error!("Failed to register service: {:?}", e);
                    e
                })?;

            info!("Service {} registered successfully", self.config.name);
        } else {
            warn!("No registry configured, service will not be registered");
        }

        // 保存服务实例信息
        self.service_instance = Some(service_instance.clone());
        
        // 标记为已启动
        self.started.store(true, std::sync::atomic::Ordering::Release);

        info!("RustCloud application '{}' started successfully on {}:{}", 
              self.config.name, 
              service_instance.host, 
              service_instance.port);

        // 设置优雅关闭处理
        self.setup_graceful_shutdown().await?;

        Ok(())
    }

    /// 设置优雅关闭处理
    async fn setup_graceful_shutdown(self) -> ServiceResult<()> {
        // 等待关闭信号
        tokio::select! {
            _ = signal::ctrl_c() => {
                info!("Received Ctrl+C, starting graceful shutdown...");
            }
            _ = self.wait_for_termination() => {
                info!("Received termination signal, starting graceful shutdown...");
            }
        }

        self.shutdown().await
    }

    /// 等待终止信号（Unix系统）
    #[cfg(unix)]
    async fn wait_for_termination(&self) {
        use tokio::signal::unix::{signal, SignalKind};
        
        let mut sigterm = signal(SignalKind::terminate()).expect("Failed to register SIGTERM handler");
        let mut sigint = signal(SignalKind::interrupt()).expect("Failed to register SIGINT handler");
        
        tokio::select! {
            _ = sigterm.recv() => {},
            _ = sigint.recv() => {},
        }
    }

    /// 等待终止信号（Windows系统）
    #[cfg(windows)]
    async fn wait_for_termination(&self) {
        // Windows下只支持Ctrl+C信号
        let _ = signal::ctrl_c().await;
    }

    /// 关闭应用并注销服务
    pub async fn shutdown(self) -> ServiceResult<()> {
        if !self.started.load(std::sync::atomic::Ordering::Acquire) {
            warn!("Application not started, nothing to shutdown");
            return Ok(());
        }

        info!("Shutting down RustCloud application '{}'...", self.config.name);

        // 如果有注册的服务实例，则注销服务
        if let (Some(registry), Some(instance)) = (&self.registry, &self.service_instance) {
            info!("Deregistering service {} from registry", self.config.name);
            
            match registry.deregister(instance.clone()).await {
                Ok(_) => info!("Service {} deregistered successfully", self.config.name),
                Err(e) => error!("Failed to deregister service {}: {:?}", self.config.name, e),
            }
        }

        info!("RustCloud application '{}' shut down successfully", self.config.name);
        Ok(())
    }

    /// 获取应用配置
    pub fn config(&self) -> &ApplicationConfig {
        &self.config
    }

    /// 获取服务实例信息
    pub fn service_instance(&self) -> Option<&ServiceInstance> {
        self.service_instance.as_ref()
    }

    /// 检查应用是否已启动
    pub fn is_started(&self) -> bool {
        self.started.load(std::sync::atomic::Ordering::Acquire)
    }
}

/// RustCloud 应用构建器
///
/// 提供了一种链式调用的方式来构建和配置 RustCloud 应用。
/// 相比直接创建 ApplicationConfig，构建器模式提供了更好的可读性和灵活性。
/// 支持逐步配置应用的各种属性，最后通过 build() 方法创建应用实例。
///
/// # 构建器模式优势
///
/// * **链式调用** - 支持方法链式调用，代码更简洁
/// * **可选配置** - 只需要设置需要的配置项
/// * **类型安全** - 编译时检查配置的有效性
/// * **默认值** - 自动应用合理的默认配置
/// * **清晰易读** - 配置过程更加直观和易理解
///
/// # 使用流程
///
/// 1. **创建构建器** - 使用 new() 或 from_config() 创建构建器
/// 2. **配置属性** - 通过链式调用设置各种属性
/// 3. **设置注册中心** - 可选地配置服务注册中心
/// 4. **构建应用** - 调用 build() 创建最终的应用实例
///
/// # 完整使用示例
///
/// ```rust
/// use rustcloud_core::application::{RustCloudApplicationBuilder, RustCloudApplication};
/// use std::sync::Arc;
///
/// #[tokio::main] 
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
///     let app = RustCloudApplicationBuilder::new()
///         .name("user-service")
///         .version("1.2.3")
///         .port(8080)
///         .host("0.0.0.0")
///         .group("backend-services")
///         .namespace("production")
///         .metadata("team", "user-team")
///         .metadata("environment", "prod")
///         // .registry(my_registry)  // 可选的注册中心
///         .build();
///         
///     app.run().await?;
///     Ok(())
/// }
/// ```
///
/// # 配置验证
///
/// 构建器会在 build() 时进行基本的配置验证，但完整的验证在应用启动时进行。
/// 建议在开发阶段测试所有配置组合以确保配置的正确性。
pub struct RustCloudApplicationBuilder {
    /// 应用配置对象
    config: ApplicationConfig,
    /// 可选的注册中心实例
    registry: Option<Arc<dyn ServiceRegistry>>,
}

impl RustCloudApplicationBuilder {
    /// 创建新的应用构建器
    pub fn new() -> Self {
        Self {
            config: ApplicationConfig::default(),
            registry: None,
        }
    }

    /// 从配置创建应用构建器
    pub fn from_config(config: ApplicationConfig) -> Self {
        Self {
            config,
            registry: None,
        }
    }

    /// 设置应用名称
    pub fn name<S: Into<String>>(mut self, name: S) -> Self {
        self.config.name = name.into();
        self
    }

    /// 设置应用版本
    pub fn version<S: Into<String>>(mut self, version: S) -> Self {
        self.config.version = version.into();
        self
    }

    /// 设置服务端口
    pub fn port(mut self, port: u16) -> Self {
        self.config.port = port;
        self
    }

    /// 设置服务主机地址
    pub fn host<S: Into<String>>(mut self, host: S) -> Self {
        self.config.host = Some(host.into());
        self
    }

    /// 设置服务分组
    pub fn group<S: Into<String>>(mut self, group: S) -> Self {
        self.config.group = Some(group.into());
        self
    }

    /// 设置命名空间
    pub fn namespace<S: Into<String>>(mut self, namespace: S) -> Self {
        self.config.namespace = Some(namespace.into());
        self
    }

    /// 添加元数据
    pub fn metadata<K: Into<String>, V: Into<String>>(mut self, key: K, value: V) -> Self {
        self.config.metadata.insert(key.into(), value.into());
        self
    }

    /// 设置注册中心
    pub fn registry(mut self, registry: Arc<dyn ServiceRegistry>) -> Self {
        self.registry = Some(registry);
        self
    }

    /// 构建RustCloud应用
    pub fn build(self) -> RustCloudApplication {
        let mut app = RustCloudApplication::new(self.config);
        if let Some(registry) = self.registry {
            app = app.with_registry(registry);
        }
        app
    }
}

impl Default for RustCloudApplicationBuilder {
    fn default() -> Self {
        Self::new()
    }
}

// RunConfig 已移除，因为它引用了已移至其他模块的配置结构体

#[cfg(test)]
mod tests {
    use super::*;
    use crate::RegistryType;

    #[test]
    fn test_application_builder() {
        let app = RustCloudApplicationBuilder::new()
            .name("test-service")
            .version("1.0.0")
            .port(8080)
            .host("127.0.0.1")
            .group("default")
            .namespace("public")
            .metadata("env", "test")
            .build();

        let config = app.config();
        assert_eq!(config.name, "test-service");
        assert_eq!(config.version, "1.0.0");
        assert_eq!(config.port, 8080);
        assert_eq!(config.host, Some("127.0.0.1".to_string()));
        assert_eq!(config.group, Some("default".to_string()));
        assert_eq!(config.namespace, Some("public".to_string()));
        assert_eq!(config.metadata.get("env"), Some(&"test".to_string()));
    }

    #[test]
    fn test_service_instance_building() {
        let config = ApplicationConfig {
            name: "test-service".to_string(),
            version: "1.0.0".to_string(),
            port: 8080,
            host: Some("127.0.0.1".to_string()),
            ..Default::default()
        };

        let app = RustCloudApplication::new(config);
        let instance = app.build_service_instance();

        assert_eq!(instance.service_id, "test-service");
        assert_eq!(instance.host, "127.0.0.1");
        assert_eq!(instance.port, 8080);
        assert_eq!(instance.scheme, "http");
        assert_eq!(instance.get_metadata("version"), Some("1.0.0"));
    }
}